using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using Caliburn.Micro;
using MediaOwl.Common;
using MediaOwl.Common.Messages;
using MediaOwl.Common.ScreenManagement;
using MediaOwl.LastFm.Data;
using MediaOwl.LastFm.Model;

namespace MediaOwl.LastFm.ViewModels
{
    [Export, PartCreationPolicy(CreationPolicy.NonShared)]
    public class MusicTagSingleViewModel : Workitem<LastFmViewModel>
    {
        #region Fields
        private readonly ILastFmDataRepository repository;
        private readonly IEventAggregator eventAggregator;

        #endregion

        #region Constructor
        [ImportingConstructor]
        public MusicTagSingleViewModel(ILastFmDataRepository repository, IEventAggregator eventAggregator)
        {
            this.repository = repository;
            this.eventAggregator = eventAggregator;
        }

        #endregion

        #region Properties & Backingfields

        private Tag currentTag;
        public Tag CurrentTag
        {
            get { return currentTag; }
            set
            {
                currentTag = value;
                NotifyOfPropertyChange(() => CurrentTag);
                NotifyOfPropertyChange(() => TopArtists);
                NotifyOfPropertyChange(() => TopAlbums);
                NotifyOfPropertyChange(() => TopTracks);
                NotifyOfPropertyChange(() => WeeklyArtistChart);
            }
        }

        public IList<Artist> TopArtists
        {
            get { return CurrentTag == null ? null : CurrentTag.Artists; }
        }
        public IList<Album> TopAlbums
        {
            get { return CurrentTag == null ? null : CurrentTag.Albums; }
        }
        public IList<Track> TopTracks
        {
            get { return CurrentTag == null ? null : CurrentTag.Tracks; }
        }
        public IList<Artist> WeeklyArtistChart
        {
            get { return CurrentTag == null ? null : CurrentTag.WeeklyArtistChart; }
        }

        #endregion

        #region Methods

        public void WithTag(Tag tag)
        {
            if (tag == null)
                return;

            CurrentTag = tag;
            DisplayName = "Tag: \'" + CurrentTag.Name + "\'";
            Run.Coroutine(FetchInfo());
        }

        private IEnumerator<IResult> FetchInfo()
        {
            yield return Show.Busy(this);

            if (CurrentTag != null)
            {
                yield return repository.GetTopArtistsOfTag(CurrentTag,
                                                           x => CurrentTag.Artists = x.ToList(),
                                                           x => eventAggregator.Publish(new ErrorMessage(x)));

                yield return repository.GetTopAlbumsOfTag(CurrentTag,
                                                          x => CurrentTag.Albums = x.ToList(),
                                                          x => eventAggregator.Publish(new ErrorMessage(x)));

                yield return repository.GetTopTracksOfTag(CurrentTag,
                                                          x => CurrentTag.Tracks = x.ToList(),
                                                          x => eventAggregator.Publish(new ErrorMessage(x)));

                IEnumerable<Artist> weeklyArtistChart = null;
                yield return repository.GetWeeklyArtistChartOfTag(CurrentTag,
                                                                  x => weeklyArtistChart = x.ToList(),
                                                                  x => eventAggregator.Publish(new ErrorMessage(x)));

                double hightestWeight = 0d;
                CurrentTag.WeeklyArtistChart = new List<Artist>();
                foreach (var a in weeklyArtistChart)
                {
                    if (CurrentTag.WeeklyArtistChart.Count == 0)
                        hightestWeight = a.Weight;

                    if (hightestWeight > 0)
                        a.Points = Math.Round(a.Weight/hightestWeight*300d, 1);

                    CurrentTag.WeeklyArtistChart.Add(a);
                }

                NotifyOfPropertyChange(() => CurrentTag);
                NotifyOfPropertyChange(() => TopArtists);
                NotifyOfPropertyChange(() => TopAlbums);
                NotifyOfPropertyChange(() => TopTracks);
                NotifyOfPropertyChange(() => WeeklyArtistChart);
            }
            yield return Show.NotBusy(this);
        }

        public IEnumerator<IResult> OpenArtist(object selectedItem)
        {
            if (selectedItem is Artist)
            {
                yield return Show.Child<MusicArtistSingleViewModel>(Helper.GetScreenId((Artist)selectedItem))
                    .In(Parent)
                    .Configured(x => x.WithArtist((Artist)selectedItem));
            }
        }

        public IEnumerator<IResult> OpenAlbum(object selectedItem)
        {
            if (selectedItem is Album)
            {
                yield return Show.Child<MusicAlbumSingleViewModel>(Helper.GetScreenId((Album)selectedItem))
                    .In(Parent)
                    .Configured(x => x.WithAlbum((Album)selectedItem));
            }
        }

        public IEnumerator<IResult> OpenTrack(object selectedItem)
        {
            if (selectedItem is Track)
            {
                yield return Show.Child<MusicTrackSingleViewModel>(Helper.GetScreenId((Track)selectedItem))
                    .In(Parent)
                    .Configured(x => x.WithTrack((Track)selectedItem));
            }
        }

        #endregion
    }
}